package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.injector.methods.SelectList;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.enums.UserType;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author 陈宽
 * @since 2025-07-02
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final UserClient userClient;
    private final InteractionQuestionMapper questionMapper;


    @Override
    public void hiddenReply(Long id, Boolean hidden) {
        //1.先查询回答或者评论是否存在
        InteractionReply reply = this.getById(id);
        if (ObjectUtils.isEmpty(reply)) {
            throw new RuntimeException("回答不存在");
        }
        //2.修改回答或者评论的状态
        reply.setHidden(hidden);
        this.updateById(reply);
        if (reply.getAnswerId() != null && reply.getAnswerId() != 0 && reply.getReplyTimes() == 0) {
            return;
        }
        //3.修改评论的状态
        this.lambdaUpdate()
                .eq(InteractionReply::getAnswerId, reply.getId())
                .set(InteractionReply::getHidden, hidden);
    }

    @Override
    public ReplyVO queryReplyById(Long id) {
        //1.根据查询回答或者评论
        InteractionReply replyPo = getById(id);
        if (ObjectUtils.isEmpty(replyPo)) {
            return null;
        }
        //2.创建一个ReplyVO
        ReplyVO replyVO = BeanUtils.toBean(replyPo, ReplyVO.class);
        //3.根据po的userId和targetUserId查询回答或者评论的用户信息
        Set<Long> userIds = Set.of(replyPo.getUserId(), replyPo.getTargetUserId());
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        replyVO.setUserName(userMap.get(replyPo.getUserId()).getName());
        replyVO.setUserIcon(userMap.get(replyPo.getUserId()).getIcon());
        replyVO.setUserType(userMap.get(replyPo.getUserId()).getType());
        //4.根据po的answerId是否为0或者null来判断时候为回答
        if (replyPo.getAnswerId() == null || replyPo.getAnswerId() == 0) {
            //4.1是回答就根据根据po的id来查询出评论的数量
            Integer count = lambdaQuery()
                    .eq(InteractionReply::getAnswerId, replyPo.getId())
                    .count();
            replyVO.setReplyTimes(count);
        } else {
            //4.2是评论就给vo的targetUserName赋值
            replyVO.setTargetUserName(userMap.get(replyPo.getTargetUserId()).getName());
        }
        return replyVO;
    }

    @Override
    public void saveReply(ReplyDTO replyDTO) {
        //1.根据answerId是否为0或者null来判断是回复还是评论
        boolean isComment = ObjectUtils.isNotNull(replyDTO.getAnswerId()) && replyDTO.getAnswerId() != 0;
        //2.创建po对象，toBean
        InteractionReply replyPo = BeanUtils.toBean(replyDTO, InteractionReply.class);
        //3.setUserId
        replyPo.setUserId(UserContext.getUser());
        //4.保存
        save(replyPo);
        //5.是回答
        if (!isComment) {
            //5.1要更新问题表：问题的最近一次回答ID、回答数量+1、
            //更新问题表中查看状态为未查看 (如果是学生回答)
            LambdaUpdateWrapper<InteractionQuestion> swapper = new LambdaUpdateWrapper<>();
            swapper.eq(InteractionQuestion::getId, replyPo.getQuestionId())
                    .set(InteractionQuestion::getLatestAnswerId, replyPo.getId())
                    .set(replyDTO.getIsStudent(), InteractionQuestion::getStatus, 0)
                    .setSql("answer_times = answer_times+1");
            questionMapper.update(null, swapper);
        } else {
            //6.是评论
            //6.1 需要更新回复表：回答的评论数量+1
            this.lambdaUpdate()
                    .eq(InteractionReply::getId, replyDTO.getAnswerId())
                    .setSql("reply_times = reply_times+1");
        }
    }

    @Override
    public PageDTO<ReplyVO> queryReplyPage(ReplyPageQuery pageQuery, boolean isStudent) {
        //1.判断pageQuery的数据是否合法，两个不能同时为空
        Long answerId = pageQuery.getAnswerId();
        Long questionId = pageQuery.getQuestionId();
        if(ObjectUtils.isEmpty(questionId)&&ObjectUtils.isEmpty(answerId)){
            throw new BadRequestException("参数有误");
        }
        //2.判断pageQuery的answerId是否为0或者为null，
        //是就是评论
        boolean isReply = ObjectUtils.isEmpty(answerId) || answerId == 0;
        //3.分页查询
        //3.1 是回答就eq questionId
        //3.2 三元运算符是评论就eq answerId，否则eq 0
        //3.3 是学生就eq hidden = false
        //3.4 根据点赞数排序，点赞数相同，再按照创建时间排序
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(isReply, InteractionReply::getQuestionId, questionId)
                .eq(InteractionReply::getAnswerId, isReply ? 0 : answerId)
                .eq(isStudent, InteractionReply::getHidden, false)
                .page(pageQuery.toMpPage(
                        new OrderItem("liked_times", false),
                        new OrderItem("create_time", false)
                ));
        if (ObjectUtils.isEmpty(page)){
            return PageDTO.empty(page);
        }
        //3.5 获得records
        List<InteractionReply> records = page.getRecords();
        //3.6 循环得到userId和targetUserId和replyId，targetReplyId
        Set<Long> userIds = new HashSet<>();
        Set<Long> targetUserIds = new HashSet<>();
        Set<Long> replyIds = new HashSet<>();
        Set<Long> targetReplyIds = new HashSet<>();
        for (InteractionReply record : records) {
            userIds.add(record.getUserId());
            userIds.add(record.getTargetUserId());
            replyIds.add(record.getId());
            if (!isReply){
                targetUserIds.add(record.getTargetUserId());
                targetReplyIds.add(record.getTargetReplyId());
            }
        }
        //4.UserClint通过userId和targetUserId得到userNames
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userInfoMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        //5.当是回答，计算replyTimes，只返回没有被隐藏的
        //5.0 select("answer_Id as id,count(1)")
        //5.1 eq hidden = false
        //5.2 answerId in replyId
        //5.3 groupBy answerId
        Map<Long, Integer> replyNumMap  = new HashMap<>();
        if(isReply){
            List<InteractionReply> list = this.query()
                    .select("answer_id as id,count(1) as num")
                    .eq("hidden", false)
                    .in("answer_id", replyIds)
                    .groupBy("answer_id")
                    .list();
            replyNumMap = list.stream().collect(Collectors.toMap(InteractionReply::getId, InteractionReply::getNum));
        }
        //6.当是评论而且是学生
        Map<Long, Boolean> isAnonymity = new HashMap<>();
        if (!isReply && isStudent && ObjectUtils.isNotEmpty(targetReplyIds)){
            //6.1 根据targetReplyIds查询出所有被评论的reply
            List<InteractionReply> interactionReplies = listByIds(targetReplyIds);
            //6.2 转换成Map<Long, Boolean>用来判断上一级有没有匿名
            isAnonymity = interactionReplies.stream().collect(Collectors.toMap(InteractionReply::getId, InteractionReply::getAnonymity));
        }
        //7.创建一个QuestionVO的questionVOList
        List<ReplyVO> VOList = new ArrayList<>();
        //8.循环records
        for (InteractionReply record : records) {
            //8.1 创建一个QuestionVO vo
            ReplyVO vo = BeanUtils.toBean(record, ReplyVO.class);
            //8.2 当不是学生或者不是匿名，设置
            if (!isStudent|| !record.getAnonymity()){
                //userIcon
                vo.setUserIcon(userInfoMap.get(record.getUserId()).getIcon());
                //userName
                vo.setUserName(userInfoMap.get(record.getUserId()).getName());
            }
            //8.3 是评论，而且(不是学生或者目标不是匿名)
            //填充targetUserName
            if (!isReply&&(!isStudent|| !isAnonymity.get(record.getTargetReplyId()))){
                vo.setTargetUserName(userInfoMap.get(record.getTargetUserId()).getName());
            }
            //8.4 是回答，就返回replyTimes
            if (isReply){
                vo.setReplyTimes(replyNumMap.get(record.getId()));
            }
            //8.5 TODO 填充likedTimes liked
            //8.6 questionVOList.add(vo)
            VOList.add(vo);
        }
        // 9、如果是回答，则需要更新问题状态为已查看
        if(isReply && !isStudent){
            LambdaUpdateWrapper<InteractionQuestion> swapper = new LambdaUpdateWrapper<>();
            swapper.set(InteractionQuestion::getStatus, QuestionStatus.CHECKED)
                    .eq(InteractionQuestion::getId, questionId);
            this.questionMapper.update(null,swapper);
        }
        //10.返回PageDTO.of(page.getPages(),page.getTotal(),questionVOList);
        return PageDTO.of(page.getPages(),page.getTotal(),VOList);
    }
}
